package partyBrookerHameln;
import java.util.ArrayList;

/**
 * Ein Objekt der Klasse Kunde hat einen Vor- und Zunamen, eine eindeutige
 * Kundennummer, eine Liste mit seinen Transaktionen mit einer Umsatzsumme. Ein
 * Kunde kann Gegenstände kaufen, leihen und zurückgeben (in Form von
 * Transaktionen), aber auch ausgewählte Transaktionen anzeigen lassen. Die
 * nicht bezahlten Transaktionen können zusammen abgerechnet werden und die
 * Kundennamen lassen sich ändern.
 */
public class Kunde {
	private String name, vorname;
	private int kundenNummer;
	private double gesamtUmsatz;
	private ArrayList<Transaktion> TransaktionsListe = new ArrayList<Transaktion>();

	/**
	 * Der Konstruktor der Kunde Klasse. Er bekommt den Namen, Vornamen und die
	 * Kundennummer des neuen Kunden übergeben.
	 * 
	 * @param name
	 *            Der Nachname des zu erstellenden Kunden
	 * @param vorname
	 *            Der Vorname des zu erstellenden Kunden
	 * @param kundenNummer
	 *            Die automatisch generierte Kundennummer für diesen Kunden
	 * 
	 */
	public Kunde(String name, String vorname, int kundenNummer) {
		this.name = name;
		this.vorname = vorname;
		this.kundenNummer = kundenNummer;
		gesamtUmsatz = 0;
	}

	/**
	 * Die Methode gibt zunächst die offenen Transaktionen aus und rechnet die
	 * Service-Transaktionen des ausgewählten Kunden ab.
	 * 
	 * @return Die kumulierten Gesamtkosten aller offenen Service-Transaktionen
	 *         des Kunden als double
	 * */
	public double serviceAbrechnen() {
		double gesamtkosten = 0;
		int i = TransaktionsListe.size() - 1;
		System.out.println("Zu zahlender Service: \n ");
		System.out.println("╔════╦═══════════════════════════════════╦════╦═════════════════╦═════════════════╦════╦════╦════╦════════╗");
		System.out.println("║TrNr║                         Gegenstand║Anz.║Kauf/Ausleihdatum║      Ablaufdatum║Zrük║Verl║Bez.║ Umsatz ║");
		System.out.println("╠════╬═══════════════════════════════════╬════╬═════════════════╬═════════════════╬════╬════╬════╬════════╣");
		System.out.println("║" + formatBlanks(String.valueOf(i), 4) + TransaktionsListe.get(i).toString());
		System.out.println("╚════╩═══════════════════════════════════╩════╩═════════════════╩═════════════════╩════╩════╩════╩════════╝");

		if (!TransaktionsListe.get(i).getabgeschlossen() && TransaktionsListe.get(i).getobjekt().getService()) {
			gesamtkosten = gesamtkosten + ((Verkauf) TransaktionsListe.get(i)).gebuehrenBerechnen();
			TransaktionsListe.get(i).setAbgeschlossen(true);
		}
		gesamtUmsatz += gesamtkosten;

		return gesamtkosten;
	}

	/**
	 * Die Methode geht die Transaktionsliste des Kunden durch und rechnet alle
	 * offenen Verkäufe und Verleihe ab
	 * 
	 * @param dayDate
	 *            Der aktuelle Tag den die Methode übergeben bekommt
	 * @return Die Methode gibt die kumulierten Gesamtkosten aller offenen
	 *         Transaktionen (Verkäufe und Verleih) des Kunden zurück
	 * */
	public double kundenAbrechnen(Datum dayDate) {
		double gesamtkosten = 0;
		System.out.println("Offene Transaktionen: \n");
		offeneTransaktionenAuflisten();
		for (int i = 0; i < TransaktionsListe.size(); i++) {
			if (!TransaktionsListe.get(i).getabgeschlossen() && TransaktionsListe.get(i).getClass() == Verkauf.class && !TransaktionsListe.get(i).getobjekt().getService()) {

				gesamtkosten = gesamtkosten + ((Verkauf) TransaktionsListe.get(i)).gebuehrenBerechnen();
				TransaktionsListe.get(i).setAbgeschlossen(true);
			}
			if (!TransaktionsListe.get(i).getabgeschlossen() && TransaktionsListe.get(i).getClass() == Verleih.class && ((Verleih) TransaktionsListe.get(i)).getZurueckgegeben()
					&& !TransaktionsListe.get(i).getobjekt().getService()) {

				gesamtkosten = gesamtkosten + ((Verleih) TransaktionsListe.get(i)).gebuehrenBerechnen(dayDate);
				TransaktionsListe.get(i).setAbgeschlossen(true);
			}

		}

		gesamtUmsatz += gesamtkosten;
		return gesamtkosten;
	}

	/**
	 * Die offeneTransaktionenAuflisten Methode gibt alle offenen Transaktionen
	 * des Kunden aus
	 */
	public void offeneTransaktionenAuflisten() {
		System.out.println("╔════╦═══════════════════════════════════╦════╦═════════════════╦═════════════════╦════╦════╦════╦════════╗");
		System.out.println("║TrNr║                         Gegenstand║Anz.║Kauf/Ausleihdatum║      Ablaufdatum║Zrük║Verl║Bez.║ Umsatz ║");
		System.out.println("╠════╬═══════════════════════════════════╬════╬═════════════════╬═════════════════╬════╬════╬════╬════════╣");
		for (int i = 0; i < TransaktionsListe.size(); i++) {
			if (!TransaktionsListe.get(i).getabgeschlossen() && (Verleih.class == TransaktionsListe.get(i).getClass()) ? ((Verleih) TransaktionsListe.get(i)).getZurueckgegeben() : false) {
				System.out.println("║" + formatBlanks(String.valueOf(i), 4) + TransaktionsListe.get(i).toString());
			}
		}
		System.out.println("╚════╩═══════════════════════════════════╩════╩═════════════════╩═════════════════╩════╩════╩════╩════════╝");
	}

	/**
	 * Die rueckgabeTransaktionenAuflisten Methode wird vor der Rückgabe von
	 * Gegenständen aufgerufen und gibt alle offenen Verleihe auf
	 */
	public void rueckgabeTransaktionenAuflisten() {
		System.out.println("╔════╦═══════════════════════════════════╦════╦═════════════════╦═════════════════╦════╦════╦════╦════════╗");
		System.out.println("║TrNr║                         Gegenstand║Anz.║Kauf/Ausleihdatum║      Ablaufdatum║Zrük║Verl║Bez.║ Umsatz ║");
		System.out.println("╠════╬═══════════════════════════════════╬════╬═════════════════╬═════════════════╬════╬════╬════╬════════╣");
		for (int i = 0; i < TransaktionsListe.size(); i++) {
			if (!TransaktionsListe.get(i).getabgeschlossen()) {
				if (TransaktionsListe.get(i) instanceof Verleih) {
					if (!((Verleih) TransaktionsListe.get(i)).getZurueckgegeben()) {
						System.out.println("║" + formatBlanks(String.valueOf(i), 4) + TransaktionsListe.get(i).toString());
					}
				}
			}
		}
		System.out.println("╚════╩═══════════════════════════════════╩════╩═════════════════╩═════════════════╩════╩════╩════╩════════╝");
	}

	/**
	 * Die Methode prüft, ob der Kunde offene Verleih-Transaktionen hat
	 * 
	 * @return boolean true wenn offene Ausleihen vorhanden sind
	 */
	public boolean rueckgebareVorhanden() {
		boolean vorhanden = false;
		for (int i = 0; i < TransaktionsListe.size(); i++) {
			if (!TransaktionsListe.get(i).getabgeschlossen()) {
				if (TransaktionsListe.get(i) instanceof Verleih) {
					if (!((Verleih) TransaktionsListe.get(i)).getZurueckgegeben()) {
						vorhanden = true;
					}
				}
			}
		}
		return vorhanden;
	}

	/**
	 * Die transaktionenAuflisten Methode gibt alle Transaktioenen des Kunden
	 * aus, sowohl offenen als auch abgeschlossene.
	 */
	public void transaktionenAuflisten() {
		System.out.println("╔════╦═══════════════════════════════════╦════╦═════════════════╦═════════════════╦════╦════╦════╦════════╗");
		System.out.println("║TrNr║                         Gegenstand║Anz.║Kauf/Ausleihdatum║      Ablaufdatum║Zrük║Verl║Bez.║ Umsatz ║");
		System.out.println("╠════╬═══════════════════════════════════╬════╬═════════════════╬═════════════════╬════╬════╬════╬════════╣");
		for (int i = 0; i < TransaktionsListe.size(); i++) {
			System.out.println("║" + formatBlanks(String.valueOf(i), 4) + TransaktionsListe.get(i).toString());
		}
		System.out.println("╚════╩═══════════════════════════════════╩════╩═════════════════╩═════════════════╩════╩════╩════╩════════╝");
	}

	/**
	 * Die Methode fügt der Transaktionsliste des Kunden einen neuen Verleih
	 * hinzu
	 * 
	 * @param objekt
	 *            Das zu verleihende Objekt wird der Methode übergeben
	 * @param anzahl
	 *            Die zu verleihende Anzahl wird der Methode übergeben
	 * @param ausleihDatum
	 *            Das Datum des Ausleihens wird der Methode übergeben
	 * @param zeit
	 *            Die geplante Dauer des Ausleihens wird der Methode übergeben
	 * 
	 * 
	 */
	public void leihen(Gegenstand objekt, int anzahl, Datum ausleihDatum, int zeit) {
		if (objekt.verleihbar()) {
			TransaktionsListe.add(new Verleih(objekt, anzahl, ausleihDatum, zeit));
		} else {
			System.out.println("Das Objekt hinter der eingegebenen Nummer ist nicht verleihbar.");
		}
	}

	/**
	 * Die Methode fügt der Transaktionsliste des Kunden einen neuen Verkauf zu
	 * 
	 * @param objekt
	 *            das zu verkaufende Objekt wird der Methode übergeben
	 * @param anzahl
	 *            die zu verkaufende Anzahl wird der Methode übergeben
	 * @param datum
	 *            das Datum des Kaufs wird der Methode übergeben
	 * 
	 */
	public void kaufen(Gegenstand objekt, int anzahl, Datum datum) {
		if (objekt.verkaeuflich()) {
			Verkauf verkauf = new Verkauf(objekt, anzahl, datum);
			TransaktionsListe.add(verkauf);
		} else {
			System.out.println("Das Objekt hinter der eingegebenen Nummer ist nicht verkäuflich.");
		}
	}

	/**
	 * Die rueckgabe Methode regelt die Rückgabe von verliehnen Gegenständen
	 * 
	 * @param transaktion
	 *            ,die Verleih-Transaktion die die Methode übergeben bekommt und
	 *            die zurückgegeben werden soll
	 * @param objekteVerloren
	 *            anzahl der verlorenen Objekte
	 * @return dier Methode gibt das zurückgegebenen Objekt zurück. Der Bestand
	 *         ist dabei um die verlorenen Objekte verringert
	 * 
	 * 
	 */
	public Gegenstand rueckgabe(Verleih transaktion, int objekteVerloren) {

		Verleih fertig = transaktion; // Anzahl in Verleih ist Anzahl mit
										// verlorenen Objekten
		fertig.setZurueckgegeben(true);
		fertig.getobjekt().setBestand(transaktion.getAnzahl() - objekteVerloren); // Gegenstandsbestand
																					// ist
																					// zurückgegebene
																					// Anzahl
		TransaktionsListe.remove(transaktion);
		TransaktionsListe.add(fertig);
		return fertig.getobjekt();

	}

	/**
	 * Getter für den Namen Parameter
	 * 
	 * @return den Nachnamen des Kunden
	 * 
	 */
	public String getName() {
		return name;
	}

	/**
	 * Setter für den Namen Parameter
	 * 
	 * @param name
	 *            den die Methode übergeben bekommt.
	 * 
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Getter für den Vornamen Parameter
	 * 
	 * @return gibt den Vornamen des Kundne zurück
	 * 
	 */
	public String getVorname() {
		return vorname;
	}

	/**
	 * Setter für den Vornamen Parameter
	 * 
	 * @param vorname
	 *            den die Methode übergeben bekommt.
	 * 
	 */
	public void setVorname(String vorname) {
		this.vorname = vorname;
	}

	/**
	 * Getter für den Parameter Kundennummer
	 * 
	 * @return gibt die Kundennummer des Kunden zurück.
	 * 
	 * 
	 */
	public int getKundenNummer() {
		return kundenNummer;
	}

	/**
	 * Getter für die Transaktionsliste des Kunden.
	 * 
	 * @return gibt die Transaktionsliste des Kunden zurück.
	 * 
	 */
	public ArrayList<Transaktion> getTransaktionsListe() {
		return TransaktionsListe;
	}

	/**
	 * Die Methode stellt eine Zeichenkette auf eine bestimmte Länge ein, indem
	 * sie mit vorangestellten Leerzeichen aufgefüllt wird.
	 * 
	 * @param st
	 *            Der zu formatierende String
	 * @param len
	 *            Die Länge des auszugebenen String
	 * @return String Eine mit führenden Leerzeichen verlängerte Zeichenkette
	 */
	public String formatBlanks(String st, int len) {
		String result = String.valueOf(st);
		while (result.length() < len) {
			result = " " + result;
		}
		return result;
	}

	public String toString() {
		return "║" + formatBlanks(String.valueOf(kundenNummer), 12) + "║" + formatBlanks(vorname + " " + name, 30) + "║" + formatBlanks(String.valueOf(TransaktionsListe.size()), 16) + "║"
				+ formatBlanks(String.valueOf(gesamtUmsatz), 11) + "€║";
	}
}
